require 'ostruct'

class Stat < ActiveRecord::Base
  acts_as_taggable
  acts_as_versioned
  
  
  validates_presence_of :project_hash, :project_url, :created_at, :crap, :crap_load, :crap_methods, :total_methods, :ones, :twos, :fours, :eights, :sixteens, :thirtytwos, :sixtyfours, :one28s, :two56s
  validates_numericality_of :crap, :crap_load, :crap_methods, :total_methods, :ones, :twos, :fours, :eights, :sixteens, :thirtytwos, :sixtyfours, :one28s, :two56s
  validates_uniqueness_of :project_hash
  validates_presence_of :project_name, {:if => :shared == true}
  
  def Stat.all_stats
    stats = Stat.find_by_sql("SELECT COUNT(project_hash) as project_count,
                      SUM(crap) as crap_count,
                      SUM(crap_load) as crap_load_count,
                      SUM(crap_methods) as crap_method_count,
                      SUM(total_methods) as total_methods_count,
                      AVG(crap) as crap_avg,
                      STD(crap) as crap_std,
                      AVG(crap_load) as crap_load_avg,
                      STD(crap_load) as crap_load_std, 
                      AVG(crap_methods) as crap_methods_avg,
                      STD(crap_methods) as crap_methods_std, 
                      AVG(total_methods) as total_methods_avg,
                      STD(total_methods) as total_methods_std,
                      MAX(crap) as crap_max,
                      MAX(crap_load) as crap_load_max,
                      MAX(crap_methods) as crap_methods_max,
                      MAX(total_methods) as total_methods_max
                 from stats")
    
#    puts "CRAP == #{test}"
   return stats[0] unless stats[0].project_count.to_i == 0
   
   return self.empty_stat
  end
  
  def empty_stat
   stat = OpenStruct.new
   stat.project_count = 0
   stat.crap_count = 0
   stat.crap_load_count  = 0
   stat.crap_method_count = 0
   stat.total_methods_count = 0
   stat.crap_avg = 0
   stat.crap_std = 0
   stat.crap_load_avg = 0
   stat.crap_load_std = 0
   stat.crap_methods_avg = 0
   stat.crap_methods_std = 0
   stat.total_methods_avg = 0
   stat.total_methods_std = 0
   stat.crap_max = 0
   stat.crap_load_max = 0
   stat.crap_methods_max = 0
   stat.total_methods_max = 0
   return stat
  end
  
  def self.all_stats_tagged(tags)
    tag_ids = tags.map {|t| t.id } 
    stats = Stat.find_by_sql("SELECT COUNT(project_hash) as project_count,
                      SUM(crap) as crap_count,
                      SUM(crap_load) as crap_load_count,
                      SUM(crap_methods) as crap_method_count,
                      SUM(total_methods) as total_methods_count,
                      AVG(crap) as crap_avg,
                      STD(crap) as crap_std,
                      AVG(crap_load) as crap_load_avg,
                      STD(crap_load) as crap_load_std, 
                      AVG(crap_methods) as crap_methods_avg,
                      STD(crap_methods) as crap_methods_std, 
                      AVG(total_methods) as total_methods_avg,
                      STD(total_methods) as total_methods_std,
                      MAX(crap) as crap_max,
                      MAX(crap_load) as crap_load_max,
                      MAX(crap_methods) as crap_methods_max,
                      MAX(total_methods) as total_methods_max
                 from stats where stats.id in (select taggable_id from taggings where tag_id in (#{tag_ids.join(',')})) ")
    return stats[0] unless stats[0].project_count.to_i == 0
    return self.empty_stat
  end
  
  def self.all_stats_tagged_with_list(tags)
    @stats = Stat.find_tagged_with(tags)
    stat_ids = @stats.map {|s| s.id }
    stats = Stat.find_by_sql("SELECT COUNT(project_hash) as project_count,
                      SUM(crap) as crap_count,
                      SUM(crap_load) as crap_load_count,
                      SUM(crap_methods) as crap_method_count,
                      SUM(total_methods) as total_methods_count,
                      AVG(crap) as crap_avg,
                      STD(crap) as crap_std,
                      AVG(crap_load) as crap_load_avg,
                      STD(crap_load) as crap_load_std, 
                      AVG(crap_methods) as crap_methods_avg,
                      STD(crap_methods) as crap_methods_std, 
                      AVG(total_methods) as total_methods_avg,
                      STD(total_methods) as total_methods_std,
                      MAX(crap) as crap_max,
                      MAX(crap_load) as crap_load_max,
                      MAX(crap_methods) as crap_methods_max,
                      MAX(total_methods) as total_methods_max
                 from stats where stats.id in (#{stat_ids.join(',')}) ")
    return stats[0] unless stats[0].project_count.to_i == 0
    return self.empty_stat
  end
  
  def self.find_crap_total
    return Stat.find_by_sql("SELECT crap as crap,
                      total_methods as total_methods
                 from stats")
  end
  
  def self.find_crap_total_for_tagged(tags)
    stats = Stat.find_tagged_with(tags)
    stats.map {|s| [s.total_methods, s.crap]}
#    return Stat.find_by_sql("SELECT crap as crap,
#                      total_methods as total_methods
#                 from stats, taggings, tags where ((tags.id in ")
  end


  def project_name
    if !shared?
      return "Not Shared"
    elsif !self[:project_name].nil?
      self[:project_name]
    elsif self[:project_url].nil?
      "url not set"
    else
      if self[:project_url].include? '\\'
        self[:project_url].split('\\').last
      else
        self[:project_url].split('/').last
      end      
    end
  end
  
  def project_homepage
    if !shared?
      "Not Shared"
    elsif project_homepage_set?
      homepage = self[:project_homepage]
      if !homepage.starts_with?('http://')
        "http://#{homepage}"
      else
        homepage
      end
    else
      ""
    end
  end
  
  def project_homepage_set?
     !self[:project_homepage].blank?
  end
  
  def project_url(force = false)
    if !shared? && !force
      "Not Shared"
    else
      self[:project_url]
    end
  end

end
